#include "config.h"
#ifdef CONFIG_USE_NVS
#include "nvs.h"
#include "nvs_flash.h"
#include "string.h"

#include "esp_log.h"
#define TAG "config_nvs"
#define log_e(...) ESP_LOGE(TAG, __VA_ARGS__)
#define log_i(...) ESP_LOGI(TAG, __VA_ARGS__)
#define log_w(...) ESP_LOGW(TAG, __VA_ARGS__)

#define CONFIG_NVS_USE_DEFAULT_PARTITION 1
#ifndef CONFIG_NVS_USE_DEFAULT_PARTITION
#define CONFIG_NVS_PARTITION "nvs"
#endif // ! CONFIG_NVS_USE_DEFAULT_PARTITION

static const char *const namespace = "config";

static uint8_t config_nvs_buffer[4096];
bool config_init(char *name)
{
    (void)name;
#ifndef CONFIG_NVS_USE_DEFAULT_PARTITION
    ESP_ERROR_CHECK(nvs_flash_init_partition(CONFIG_NVS_PARTITION));
#endif
    return true;
}
bool config_commit(void)
{
    return true;
}

uint16_t config_find(char *name, uint8_t *data, uint16_t max_len)
{
    nvs_handle_t nvs;
#ifndef CONFIG_NVS_USE_DEFAULT_PARTITION
    esp_err_t err = nvs_open_from_partition(CONFIG_NVS_PARTITION, namespace, NVS_READONLY, &nvs);
#else
    esp_err_t err = nvs_open(namespace, NVS_READONLY, &nvs);
#endif
    if (err == ESP_OK)
    {
        size_t len;

        if ((err = nvs_get_blob(nvs, name, NULL, &len)) == ESP_OK)
        {
            if (!max_len)
                return len;
            if (len > max_len)
            {
                log_w("nvs_get_blob: len(%d) > buffer size(%d)", len, max_len);
                return 0;
            }
            if ((err = nvs_get_blob(nvs, name, data, &len)) == ESP_OK)
                return len;
        }
        nvs_close(nvs);
    }
    return 0;
}

uint16_t config_get(char *name, uint8_t *data, uint16_t max_len)
{
    return config_find(name, data, max_len);
}

bool config_set(char *name, uint16_t len, uint8_t *data)
{
    nvs_handle_t nvs;
    bool res = false;
#ifndef CONFIG_NVS_USE_DEFAULT_PARTITION
    esp_err_t err = nvs_open_from_partition(CONFIG_NVS_PARTITION, namespace, NVS_READWRITE, &nvs);
#else
    esp_err_t err = nvs_open(namespace, NVS_READWRITE, &nvs);
#endif
    if (err == ESP_OK)
    {
        if ((err = nvs_set_blob(nvs, name, data, len)) == ESP_OK)
        {
            if ((err = nvs_commit(nvs)) == ESP_OK)
                res = true;
            else
                log_e("set %s data(%d) err nvs_commit: %s", name, len, esp_err_to_name(err));
        }
        nvs_close(nvs);
    }
    return res;
}
#endif